package protobuf;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import lombok.extern.slf4j.Slf4j;
import protobuf.bean.StudentProto;

import javax.net.ssl.SSLException;
import java.security.cert.CertificateException;

@Slf4j
public class NettyProtocolBuffersClient {
    public static void main(String[] args) throws CertificateException, SSLException, InterruptedException {


        startServer();

    }

    private static void startServer() {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1);
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup)
                    .channel(NioSocketChannel.class) // 这里通道是客户端通道，而不是服务端的NioServerSocketChannel
                    .handler(new ChannelInitializer<Channel>(){

                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();

                            //Protobuf 的编码器和解码器
                            pipeline.addLast(new ProtobufVarint32FrameDecoder());
                            pipeline.addLast(new ProtobufDecoder(StudentProto.Student.getDefaultInstance()));
                            pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
                            pipeline.addLast(new ProtobufEncoder());

                            pipeline.addLast(new SimpleChannelInboundHandler<StudentProto.Student>() {
                                @Override
                                public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                    System.out.println("连通后，发送消息");

                                    StudentProto.Student student = StudentProto.Student.newBuilder()
                                            .setAge(28)
                                            .setClasses("高三")
                                            .setName("张三")
                                            .build();
                                    ctx.channel().writeAndFlush(student);
                                }

                                @Override
                                protected void channelRead0(ChannelHandlerContext ctx, StudentProto.Student msg) throws Exception {
                                    System.out.println("接收消息");
                                    System.out.println("name:" + msg.getName());
                                    System.out.println("age:" + msg.getAge());
                                    System.out.println("classes:" + msg.getClasses());

                                    ctx.channel().close().addListener((ChannelFutureListener) future -> {
                                        if (future.isSuccess()) {
                                            // Channel关闭成功
                                            System.out.println("Channel关闭成功");
                                        } else {
                                            // Channel关闭失败
                                            System.out.println("Channel关闭失败");
                                        }
                                    });
                                }
                            });
                        }
            });
            //与对应的url建立连接通道
            ChannelFuture channelFuture = bootstrap.connect("localhost",8080).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            eventLoopGroup.shutdownGracefully();
        }
    }
}